package data;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import englishChicken.Evento;

public class JDBCEventoDAO{
	
	public void delete(String uid){
		System.out.println("JDBCEventoDAO: metodo delete");
		Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	session.delete("uid",uid);
    	session.getTransaction().commit();
    }

	public void insert(String uid,Evento e){
		System.out.println("JDBCEventoDAO: metodo insert");
    	Evento s=this.selectByEID(uid);
    	if(s==null){
    		Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        	session.beginTransaction();
    		e.setUid(uid);
    		session.save(e);
        	session.flush();
        	session.getTransaction().commit();
    	}
	}
	
	public void update(Evento e){
		System.out.println("JDBCEventoDAO: metodo update");
    	Evento s=this.selectByEID(e.getUid());
    	if(s!=null){
    		Session session=HibernateUtil.getSessionFactory().getCurrentSession();
        	session.beginTransaction();
    		session.update(e);
        	session.flush();
        	session.getTransaction().commit();
    	}
	}
	
    public Evento selectByEID(String eid){
    	System.out.println("JDBCEventoDAO: metodo selectByEID");
    	return select("uid",eid);
    }
    
    public Evento selectByNombre(String nombre){
    	System.out.println("JDBCEventoDAO: metodo selectByNombre");
    	return select("nombre",nombre);
    }
    
    public Evento select(String sBy,String by){
    	System.out.println("JDBCEventoDAO: metodo select");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	Evento peticion=(Evento)session.createQuery("from Evento as u where u."+sBy+" = ?")
    	.setString(0,by)
    	.uniqueResult();
    	Hibernate.initialize(peticion);
    	Hibernate.initialize(peticion.getOrganizadoresJ());
    	Hibernate.initialize(peticion.getAsistentesJ());
    	Hibernate.initialize(peticion.getJuegosJ());
    	session.getTransaction().commit();
    	return peticion;
    }
    
    @SuppressWarnings("unchecked")
    public List<Evento> selectAll(){
    	System.out.println("JDBCEventoDAO: metodo selectAll");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	List<Evento> resultado=session.createQuery("from Evento").list();
    	Iterator<Evento> resIT=resultado.iterator();
    	while(resIT.hasNext()){
    		Evento resAct=resIT.next();
    		Hibernate.initialize(resAct);
        	Hibernate.initialize(resAct.getOrganizadoresJ());
        	Hibernate.initialize(resAct.getAsistentesJ());
        	Hibernate.initialize(resAct.getJuegosJ());
    	}
    	session.getTransaction().commit();
    	return resultado;
    }
    
    @SuppressWarnings("unchecked")
    public Integer getMaxAsistentes(){
    	System.out.println("JDBCEventoDAO: metodo getMaxAsistentes");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	List<BigInteger> q=session.createSQLQuery("select count(*) as num from uAsisteE group by eID limit 1;").list();
    	session.getTransaction().commit();
    	return q.get(0).intValue();
    }
    
    @SuppressWarnings("unchecked")
    public String getMinInicio(){
    	System.out.println("JDBCEventoDAO: metodo getMinInicio");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	List<String> q=session.createQuery("select min(fechaInicio) from Evento").list();
    	session.getTransaction().commit();
    	return q.get(0).toString();
    }
    
    @SuppressWarnings("unchecked")
    public String getMaxFin(){
    	System.out.println("JDBCEventoDAO: metodo getMaxInicio");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	List<String> q=session.createQuery("select max(fechaFinal) from Evento").list();
    	session.getTransaction().commit();
    	return q.get(0).toString();
    }
    
    @SuppressWarnings("unchecked")
    public Map<String,String> buscar(Map<String,String> p1,Map<String,String[]> p2){
    	System.out.println("JDBCEventoDAO: metodo buscar");
    	Session session=HibernateUtil.getSessionFactory().getCurrentSession();
    	session.beginTransaction();
    	
    	//Obtenemos el uid de todos los eventos y les asignamos coincidencia 0 sobre 100.
    	String q1="select new Map(e.uid as uid,0 as search) from Evento e";
    	List<Map<String,Integer>> resList=session.createQuery(q1).list();
    	Map<String,Integer> resultado=new HashMap<String,Integer>();
    	for(Map<String,Integer> resAct: resList){
    		resultado.put(String.valueOf(resAct.get("uid")),resAct.get("search"));
    	}
    	
    	//Obtenemos el uid de todos los eventos que coincidan con el nombre buscado.
    	String q2="select e.uid as uid from Evento e where e.nombre like ?";
    	List<String> resNombre=session.createQuery(q2).setString(0,"%"+p1.get("sNom")+"%").list();
    	for(String key: resNombre){
    		resultado.put(key,resultado.get(key)+35);
    	}
    	
    	//Obtenemos el uid de todas los eventos que coincidan con las fechas buscadas.
    	String q3="select e.uid from Evento e where ";
    	q3+="str_to_date(e.fechaInicio,?) >= str_to_date(?,?) and "; 
    	q3+="str_to_date(e.fechaFinal,?) <= str_to_date(?,?)";
    	List<String> resFecha=session.createQuery(q3)
    		.setString(0,"%Y-%m-%d")
    		.setString(1,p1.get("sFeI"))
    		.setString(2,"%Y-%m-%d")
    		.setString(3,"%Y-%m-%d")
    		.setString(4,p1.get("sFeF"))
    		.setString(5,"%Y-%m-%d")
    		.list();
    	for(String key: resFecha){
    		resultado.put(key,resultado.get(key)+10);
    	}
    	
    	//Obtenemos el uid de todos los eventos que coincidan con la cantidad de participantes buscada.
    	String q4="select e.uid from Evento e,uAsisteE ue where e.uid=ue.eid ";
    	q4+="group by e.uid having count(*) >= ? and count(*) <= ?;";
    	List<String> resNumPart=session.createSQLQuery(q4)
    		.setInteger(0,Integer.parseInt(p1.get("sNuM")))
    		.setInteger(1,Integer.parseInt(p1.get("sNuX")))
    		.list();
    	for(String key: resNumPart){
    		resultado.put(key,resultado.get(key)+10);
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que asisten los juegos buscados
    	if(p2.get("sJuY")!=null){
    		List<String> sJuY=Arrays.asList(p2.get("sJuY"));
    		String q5="select je.eid from jAsisteE je ";
    		q5+="where jid in (:ids) ";
    		q5+="group by je.eid having count(*) >=:tamList";
    		List<String> resJueYes=session.createSQLQuery(q5)
    			.setParameterList("ids",sJuY,Hibernate.STRING)
    			.setInteger("tamList",sJuY.size())
    			.list();
    		for(String key: resJueYes){
    			resultado.put(key,resultado.get(key)+8);
    		}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+8);
    		}
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que no asisten los juegos buscados
    	if(p2.get("sJuN")!=null){
	    	List<String> sJuN=Arrays.asList(p2.get("sJuN"));
	    	String q6="select distinct(je.eid) from jAsisteE je ";
	    	q6+="where jid in (:ids) ";
	    	List<String> resJueNo=session.createSQLQuery(q6)
	    		.setParameterList("ids",sJuN,Hibernate.STRING)
	    		.list();
	    	for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
	    	for(String key: resJueNo){
	    		resultado.put(key,resultado.get(key)-7);
	    	}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que asisten los usuarios buscados
    	if(p2.get("sUsY")!=null){
    		List<String> sUsY=Arrays.asList(p2.get("sUsY"));
    		String q7="select ue.eid from uAsisteE ue ";
    		q7+="where uid in (:ids) ";
    		q7+="group by ue.eid having count(*) >=:tamList";
    		List<String> resJueYes=session.createSQLQuery(q7)
    			.setParameterList("ids",sUsY,Hibernate.STRING)
    			.setInteger("tamList",sUsY.size())
    			.list();
    		for(String key: resJueYes){
    			resultado.put(key,resultado.get(key)+8);
    		}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+8);
    		}
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que no asisten los usuarios buscados
    	if(p2.get("sUsN")!=null){
	    	List<String> sUsN=Arrays.asList(p2.get("sUsN"));
	    	String q8="select distinct(ue.eid) from uAsisteE ue ";
	    	q8+="where ue.uid in (:ids) ";
	    	List<String> resJueNo=session.createSQLQuery(q8)
	    		.setParameterList("ids",sUsN,Hibernate.STRING)
	    		.list();
	    	for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
	    	for(String key: resJueNo){
	    		resultado.put(key,resultado.get(key)-7);
	    	}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que asisten los organizadores buscados
    	if(p2.get("sOrY")!=null){
    		List<String> sOrY=Arrays.asList(p2.get("sOrY"));
    		String q9="select ue.eid from uOrganizaE ue ";
    		q9+="where ue.uid in (:ids) ";
    		q9+="group by ue.eid";
    		List<String> resJueYes=session.createSQLQuery(q9)
    			.setParameterList("ids",sOrY,Hibernate.STRING)
    			.list();
    		for(String key: resJueYes){
    			resultado.put(key,resultado.get(key)+8);
    		}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+8);
    		}
    	}
    	
    	//Obtenemos el uid de todos los eventos a los que no asisten los organizadores buscados
    	if(p2.get("sOrN")!=null){
	    	List<String> sOrN=Arrays.asList(p2.get("sOrN"));
	    	String q10="select distinct(ue.eid) from uOrganizaE ue ";
	    	q10+="where ue.uid in (:ids) ";
	    	List<String> resJueNo=session.createSQLQuery(q10)
	    		.setParameterList("ids",sOrN,Hibernate.STRING)
	    		.list();
	    	for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
	    	for(String key: resJueNo){
	    		resultado.put(key,resultado.get(key)-7);
	    	}
    	}
    	else{
    		for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			resultado.put(e.getKey(),e.getValue()+7);
    		}
    	}
    	
    	//Ordenamos los resultados en funcion al campo search
    	SortedMap<String,String> resultadoOrdenado=new TreeMap<String,String>(Collections.reverseOrder());
    	for(Map.Entry<String,Integer> e: resultado.entrySet()){
    			String qNom="select e.nombre from Evento e where e.uid=?";
    			String nomAct=(String)session.createQuery(qNom).setString(0,e.getKey()).uniqueResult();
    			resultadoOrdenado.put("("+resultado.get(e.getKey())+") "+nomAct,e.getKey());
    	}
    	
    	//Contamos cuantos elementos genera la busqueda total sin contar los search 0
    	int numElementos=0;
    	for(Map.Entry<String,Integer> e: resultado.entrySet()){
    		if(resultado.get(e.getKey())!=0){
    			numElementos++;
    		}
    	}
    	
    	int epp=5; //Eventos por pagina
    	resultadoOrdenado.put("numeroElementos",String.valueOf(numElementos));
    	resultadoOrdenado.put("elementosPorPagina",String.valueOf(epp));
    	
    	//Mostramos los resultados por consola para comprobar que funciona bien.
    	for(Map.Entry<String,String> e: resultadoOrdenado.entrySet()){
    		System.out.println("JDBCEventoDAO - Resultado busqueda: "+e.toString());
    	}
    	
    	session.getTransaction().commit();
    	return resultadoOrdenado;
    }
}
